package io.github.bomb.batch.infrastructure.factory;

import io.github.bomb.batch.domain.BatchTask;
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JpaPagingItemReader;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import javax.persistence.EntityManagerFactory;

/**
 * JobFactory
 * 动态生成批处理任务的 Job 配置。
 */
@Component
@RequiredArgsConstructor
public class JobFactory {

	private final JobBuilderFactory jobBuilderFactory;
	private final StepBuilderFactory stepBuilderFactory;
	private final EntityManagerFactory entityManagerFactory;
	private final BeanFactory beanFactory;

	/**
	 * 根据批处理任务生成 Job。
	 */
	public Job createJob(BatchTask batchTask) {
		return jobBuilderFactory.get(batchTask.getJobName())
				.start(stepBuilderFactory.get("step-" + batchTask.getJobName())
						.<Object, Object>chunk(10)
						.reader(createReader(batchTask))
						.processor(createProcessor(batchTask))
						.writer(createWriter(batchTask))
						.build())
				.build();
	}

	@SuppressWarnings("unchecked")
	public JpaPagingItemReader<Object> createReader(BatchTask batchTask) {
		JpaPagingItemReader<Object> reader = new JpaPagingItemReader<>();
		reader.setEntityManagerFactory(entityManagerFactory);
		reader.setQueryString(batchTask.getQuery());
		reader.setPageSize(10);

		try {
			reader.afterPropertiesSet();  // 初始化 reader
		} catch (Exception e) {
			throw new RuntimeException("Failed to initialize reader", e);
		}
		return reader;
	}

	/**
	 * 动态创建处理器实例。
	 *
	 * @param batchTask 包含处理器类名的任务信息
	 * @return 动态加载的处理器
	 */
	@SuppressWarnings("unchecked")
	public ItemProcessor<Object, Object> createProcessor(BatchTask batchTask) {
		try {
			// 使用 Spring 的工具类加载处理器类
			Class<?> processorClass = ClassUtils.forName(batchTask.getProcessorClass(), this.getClass().getClassLoader());

			// 如果处理器是 Spring Bean，优先使用 Spring 容器中的实例
			if (beanFactory.containsBean(processorClass.getName())) {
				return (ItemProcessor<Object, Object>) beanFactory.getBean(processorClass);
			}

			// 如果不是 Spring Bean，则创建新实例
			return (ItemProcessor<Object, Object>) processorClass.getDeclaredConstructor().newInstance();
		} catch (Exception e) {
			throw new IllegalArgumentException("无法创建处理器实例：" + batchTask.getProcessorClass(), e);
		}
	}

	/**
	 * 动态创建写入器实例。
	 *
	 * @param batchTask 包含写入器类名的任务信息
	 * @return 动态加载的写入器
	 */
	@SuppressWarnings("unchecked")
	public ItemWriter<Object> createWriter(BatchTask batchTask) {
		try {
			// 使用 Spring 的工具类加载写入器类
			Class<?> writerClass = ClassUtils.forName(batchTask.getWriterClass(), this.getClass().getClassLoader());

			// 如果写入器是 Spring Bean，优先使用 Spring 容器中的实例
			if (beanFactory.containsBean(writerClass.getName())) {
				return (ItemWriter<Object>) beanFactory.getBean(writerClass);
			}

			// 如果不是 Spring Bean，则创建新实例
			return (ItemWriter<Object>) writerClass.getDeclaredConstructor().newInstance();
		} catch (Exception e) {
			throw new IllegalArgumentException("无法创建写入器实例：" + batchTask.getWriterClass(), e);
		}
	}

}
